from prettytable import PrettyTable
# table=PrettyTable()
# table.field_names = ["姓名", "年龄", "性别"]
# data=[["张三dedwedewdwe", 18, "ssss3s33s"], ["李四", 19, "女"], ["王五", 20, "男"]]

# for i in data[0:]:
#     table.add_row(i)
# print(table)



#======================================================================================================


def create_markdown_table(headers, rows):
    """
    生成格式良好的Markdown表格
    
    Parameters:
    headers (list): 表头列表
    rows (list): 数据行列表，每个元素是一个与表头长度相同的列表
    
    Returns:
    str: 格式化的Markdown表格字符串
    """
    # 计算每列的最大宽度
    col_count = len(headers)
    col_widths = [len(str(header)) for header in headers]
    
    for row in rows:
        for i in range(col_count):
            if i < len(row):
                col_widths[i] = max(col_widths[i], len(str(row[i])))
    
    # 创建表头行
    header_line = "|"
    for i, header in enumerate(headers):
        header_line += f" {str(header).ljust(col_widths[i])} |"
    
    # 创建分隔线
    separator = "|"
    for i in range(col_count):
        separator += f" {''.ljust(col_widths[i], '-')} |"
    
    # 创建数据行
    row_lines = []
    for row in rows:
        row_line = "|"
        for i in range(col_count):
            cell_value = str(row[i]) if i < len(row) else ""
            row_line += f" {cell_value.ljust(col_widths[i])} |"
        row_lines.append(row_line)
    
    # 组合所有部分
    table = [header_line, separator] + row_lines
    return "\n".join(table)

# 2025-09-19 17:00:15

# def print_table(rows):
#     col_widths = [max(len(str(i)) for i in col) for col in zip(*rows)]
#     # 打印分隔线，由'-'字符组成
#     # 分隔线总长度为列宽之和加列数再加1（考虑列之间的空格）
#     print('-'*(sum(col_widths)*2+len(col_widths)+1))
#     # 遍历每一行数据
#     for row in rows:
#         # 使用 enumerate 获取列索引
#         print(" | ".join(str(item).ljust(col_widths[i]) for i, item in enumerate(row)))
#         # 标题行打印后，打印分隔线
#         if row == rows[0]:
#             print('-'*(sum(col_widths)*2+len(col_widths)+1))
#     print('-'*(sum(col_widths)*2+len(col_widths)+1))
# def parse_table_string(table_str):
#     """
#     解析字符串形式的表格数据
    
#     Parameters:
#     table_str (str): 包含表格数据的多行字符串，列之间用空格分隔
    
#     Returns:
#     list: 二维列表，每个子列表代表一行数据
#     """
#     lines = table_str.strip().split('\n')
#     rows = []
#     for line in lines:
#         # 使用空格分割，并过滤掉空字符串
#         row = [cell.strip() for cell in line.split(' ') if cell.strip()]
#         rows.append(row)
#     return rows

#======================================================================================================
# v2
def get_display_width(text):
    """
    计算字符串的显示宽度（考虑中英文字符宽度差异）
    中文字符算2个宽度，英文字符算1个宽度
    """
    width = 0
    for char in str(text):
        # 判断字符是否为中文（或其他全角字符）
        if '\u4e00' <= char <= '\u9fff' or char in '，。！？；：「」（）【】《》':
            width += 2
        else:
            width += 1
    return width

def print_table(rows: list|str):
    """
    打印表格数据
    
    Parameters:
    rows (list): 二维列表，每个子列表代表一行数据

    使用使用步骤：
    rows_str = '''

    取值	含义	说明
    'inner'	内连接	只保留两个表中都存在的键值
    'outer'	外连接	保留两个表中所有的键值，缺失值用 NaN 填充
    '''

    1. 解析字符串为列表格式 
        rows = parse_table_string(rows_str)

    2. 打印表格 
        print_table(rows)

    """
    # 如果是字符串，则先解析为列表
    if isinstance(rows, str):
        rows = parse_table_string(rows)
        
    # 计算每列的最大显示宽度
    col_widths = []
    for col_idx in range(len(rows[0])):
        max_width = 0
        for row in rows:
            display_width = get_display_width(row[col_idx])
            if display_width > max_width:
                max_width = display_width
        col_widths.append(max_width)


    print('-'*(sum(col_widths)+len(col_widths)+5))
    # 打印表格
    for row in rows:
        formatted_cells = []
        
        for i, cell in enumerate(row):
            # 计算需要填充的空格数
            cell_width = get_display_width(cell)
            padding = col_widths[i] - cell_width
            formatted_cells.append(str(cell) + ' ' * padding)
        print(" | ".join(formatted_cells))
        # 标题行打印后，打印分隔线
        if row == rows[0]:
            print('-'*(sum(col_widths)+len(col_widths)+5))

    print('-'*(sum(col_widths)+len(col_widths)+5))
#======================================================================================================
# 2025-11-12 13:38:38
# def parse_table_string(table_str: str):
#     """
#     解析字符串形式的表格数据
    
#     Parameters:
#     table_str (str): 包含表格数据的多行字符串，列之间用制表符或空格分隔
    
#     Returns:
#     list: 二维列表，每个子列表代表一行数据
#     """
#     import re
    
#     lines = table_str.strip().split('\n')
#     rows = []
    
#     for line in lines:
#         line = line.strip()
#         if not line:  # 跳过空行
#             continue
            
#         # 首先尝试按制表符分割
#         if '\t' in line:
# # 使用列表推导式处理每一行数据
# # 首先通过制表符('\t')分割行数据
# # 然后对每个分割后的单元格去除首尾空白字符
# # 最后过滤掉空字符串（即去除空白单元格）
#             row = [cell.strip() for cell in line.split('\t') if cell.strip()]
#             print('line.split(\t)',line.split('\t'))
# # 打印处理后的行数据，并标注这是通过制表符分割的结果
#             print('通过tab分割',row)
#         else:
#             # 如果没有制表符，尝试按连续空格分割
#             # 使用正则表达式分割连续的空格，但保留中文之间的空格
#             row = re.split(r'\s{2,}', line)  # 两个或更多连续空格作为分隔符
#             row = [cell.strip() for cell in row if cell.strip()]
#             print('通过空格分割',row)
        
#         if row:  # 只有当行不为空时才添加
#             rows.append(row)
#     print(rows)
#     return rows
 
# 2025-11-13 10:09:28
def parse_table_string(table_str: str):
    """
    解析字符串形式的表格数据
    
    Parameters:
    table_str (str): 包含表格数据的多行字符串，列之间用制表符或空格分隔
    
    Returns:
    list: 二维列表，每个子列表代表一行数据
    """
    import re
    
    lines = table_str.strip().split('\n')
    rows = []
    max_cols = 0
    
    for line in lines:
        line = line.rstrip()  # 只去掉右侧空白
        if not line.strip():  # 跳过空行
            continue
            
        # 调试信息
        # print(f"原始行: {repr(line)}")
        
        # 处理制表符：将连续的制表符视为多个空单元格
        # 先按制表符分割，但保留空字符串
        raw_cells = line.split('\t')
        
        # 处理每个单元格，去除两端空白，但保留空字符串
        processed_cells = []
        for cell in raw_cells:
            stripped_cell = cell.strip()
            # 如果单元格中有多个连续空格，可能需要进一步分割
            if stripped_cell and re.search(r'\s{2,}', stripped_cell):
                # 按两个或更多连续空格分割
                sub_cells = re.split(r'\s{2,}', stripped_cell)
                processed_cells.extend([sc.strip() for sc in sub_cells if sc.strip()])
            else:
                processed_cells.append(stripped_cell)

        if len(processed_cells) > max_cols:
            max_cols = len(processed_cells)

    print('最大列数： ',max_cols)
    for line in lines:
        line = line.rstrip()  # 只去掉右侧空白
        if not line.strip():  # 跳过空行
            continue
            
        # 调试信息
        print(f"原始行: {repr(line)}")
        
        # 处理制表符：将连续的制表符视为多个空单元格
        # 先按制表符分割，但保留空字符串
        raw_cells = line.split('\t')
        
        # 处理每个单元格，去除两端空白，但保留空字符串
        processed_cells = []
        for cell in raw_cells:
            stripped_cell = cell.strip()
            # 如果单元格中有多个连续空格，可能需要进一步分割
            if stripped_cell and re.search(r'\s{2,}', stripped_cell):
                # 按两个或更多连续空格分割
                sub_cells = re.split(r'\s{2,}', stripped_cell)
                processed_cells.extend([sc.strip() for sc in sub_cells if sc.strip()])
            else:
                processed_cells.append(stripped_cell)

        if len(processed_cells) < max_cols:
            
            # 将每一行补足到最大列数，在列首位添加一个空字符串
            processed_cells = ['']* (max_cols - len(processed_cells)) + processed_cells
            # processed_cells += [''] * (max_cols - len(processed_cells))

        # 如果第一个单元格是空字符串，表示行首有制表符
        # 我们需要保留这些空单元格
        final_cells = []
        for cell in processed_cells:
            if cell == '':
                final_cells.append('')  # 保留空单元格
            else:
                final_cells.append(cell)
        
        if final_cells:  # 只有当行不为空时才添加
            rows.append(final_cells)

        print(f"处理后 rows: {rows}" )
    return rows
#======================================================================================================
# 2025-11-13 11:14:53
def merge_duplicate_columns(data):
    """
    合并具有相同名称的列，将内容合并到一个单元格中
    
    Parameters:
    data (list): 二维数据列表，第一行为列名
    
    Returns:
    list: 处理后的二维数据列表，重复列名已被合并
    """
    if not data:
        return data
    
    headers = data[0]
    rows = data[1:]
    
    # 查找重复的列名
    header_count = {}
    for i, header in enumerate(headers):
        if header in header_count:
            header_count[header].append(i)
        else:
            header_count[header] = [i]
    
    # 确定需要保留的列索引
    unique_headers = []
    column_groups = []  # 存储每组需要合并的列索引
    
    for header, indices in header_count.items():
        unique_headers.append(header)
        column_groups.append(indices)
    
    # 构建新的数据
    merged_data = [unique_headers]  # 第一行是去重后的列名
    
    # 处理每一行数据
    for row in rows:
        merged_row = []
        for group in column_groups:
            # 合并同一组中的所有列内容
            merged_content = []
            for idx in group:
                if idx < len(row):
                    cell_content = str(row[idx]).strip()
                    if cell_content:  # 只添加非空内容
                        merged_content.append(cell_content)
            
            # 将内容用换行符连接
            merged_cell = '\n'.join(merged_content)
            merged_row.append(merged_cell)
        merged_data.append(merged_row)
    
    return merged_data
#======================================================================================================
# 2025-11-13 11:35:01
 

def ensure_unique_header(header,dif_str='\u200B'):
    """
    确保表头唯一性，如果有重复则添加不可见字符
    
    Args:
        header: 原始表头列表
        
    Returns:
        list: 处理后的唯一表头列表
    """
    if not header:
        return header
    
    # 检查列名是否都是字符串
    for i, col_name in enumerate(header):
        if not isinstance(col_name, str):
            header[i] = str(col_name)
    
    # 检查唯一性
    if len(header) == len(set(header)):
        return header
    
    # 处理重复的列名
    seen = {}
    result = []
    
    for col_name in header:
        if col_name not in seen:
            seen[col_name] = 1
            result.append(col_name)
        else:
            # 添加零宽空格来区分重复的列名
# 创建一个新的列名，通过在原列名后添加差异字符串和已见次数
            new_name = f"{col_name}{dif_str}{seen[col_name]}"

            new_name = f"{col_name}{dif_str*seen[col_name]}"

            seen[col_name] += 1


            result.append(new_name)
    
    print(f"处理后的表头: {result}")
    return result


def validate_header_format(header, data_row=None):
    """
    验证表头格式是否符合要求
    
    Args:
        header: 表头列表
        data_row: 数据行（用于检查列数一致性）
    
    Returns:
        tuple: (是否有效, 错误信息)
    """
    if not header:
        return False, "表头不能为空"
    
    if not all(isinstance(col, str) for col in header):
        return False, "表头每个元素必须是字符串"
    
    if len(set(header)) != len(header):
        return False, "表头列名必须唯一"
    
    if data_row and len(header) != len(data_row):
        return False, f"表头列数({len(header)})与数据列数({len(data_row)})不一致"
    
    return True, "格式正确"
 
#======================================================================================================
# v3
def create_table(data: list|str, header=True, title=None):
    """
    创建并打印美观的表格
    
    Parameters:
    data (list): 二维数据列表
    header (bool): 是否使用第一行作为表头，默认为True
    title (str): 表格标题，可选
    """
    table = PrettyTable()
    

    if isinstance(data, str):
        data = parse_table_string(data)


#======================================================================================================
    # 处理表头和数据
    if header and data:

        # 如果data[0]不符和格式
        try:
            table.field_names = data[0]
        except :
            print("数据格式错误")

        # 检查并处理表头
            processed_header = ensure_unique_header(data[0],'\u200B')
            
            # 如果表头被修改过，说明原表头有重复
            if processed_header != data[0]:
                print("检测到表头有重复内容，已自动添加不可见字符确保唯一性")
            
            table.field_names = processed_header
            '''
        类型：一个字符串列表（list[str]）
要求：
列表中的每个元素必须是字符串，代表表格的一列的名称。
所有列名应该是唯一的，避免重复。
列表长度应与表格每行数据的列数一致。
            '''
# --------------------------------------------------------------------------------------------------------
        rows = data[1:]
    else:
        rows = data
        # table.field_names = [f"列{i+1}" for i in range(len(data[0]) if data else 0)]
# 设置表格的列名
# 使用列表推导式生成列名，列名从0开始递增
# 列名数量取决于数据data的第一行长度，如果data为空则列数为0
        table.field_names = [f"{i}" for i in range(len(data[0]) if data else 0)]

        table.field_names = data[0]
        rows = data[1:]
#======================================================================================================
    # # 如果需要处理表头，则先合并重复列
    # if header and data:
    #     # 合并重复列
    #     data[0] = merge_duplicate_columns(data[0])
    #     headers = data[0]
    #     rows = data[1:]
    # else:
    #     headers = [f"{i}" for i in range(len(data[0]) if data else 0)]
    #     rows = data
    
    # try:
    #     table.field_names = headers
    # except:
    #     print("数据格式错误")
    #     table.field_names = [f"列{i}" for i in range(len(headers))]
  
 
#======================================================================================================
    # 添加数据行
    for row in rows:
        i = rows.index(row)
        print(f"Row {i}: {row}, number of columns: {len(row)}")
        table.add_row(row)
    
    # 设置表格标题
    if title:
        table.title = title
    
 # 去掉水平方向的边框（包括索引列）
    # table.hrules = 1  # 1 表示只在表头下方添加分割线（FRAME格式）
    
    # 去掉垂直方向的边框（包括索引列）
    # table.vrules = 0  # 0 表示无垂直边框
    
    # 设置对齐方式
    table.align = 'c'


    print(table)
    return table



import sys
import json
import subprocess
import shutil
def copy_to_clipboard(text):
    # 如果不是字符串，则将其转换为字符串
    text = str(text)
    
    """将文本复制到剪贴板"""
    try:
        # 根据操作系统选择不同的复制命令
        if sys.platform == 'darwin':  # macOS
            subprocess.run('pbcopy', universal_newlines=True, input=text)
        elif sys.platform == 'win32':  # Windows
            subprocess.run('clip', universal_newlines=True, input=text)
        else:  # Linux
            # subprocess.run('xclip -selection clipboard', shell=True, 
            #               universal_newlines=True, input=text)
            try:
                # 确保文本是字符串
                if not isinstance(text, str):
                    text = str(text)
                
                # 使用subprocess.run()而不是Popen，以便捕获错误
                result = subprocess.run(
                    ['xclip', '-selection', 'clipboard'],
                    input=text,
                    text=True,
                    capture_output=True,
                    timeout=0.5  # 设置超时时间
                )
                
                if result.returncode == 0:
                    return True
                else:
                    print(f"xclip错误: {result.stderr}")
                    return False
                    
            except subprocess.TimeoutExpired:
                print("xclip执行超时")
                return False
            except Exception as e:
                print(f"复制到剪贴板时发生错误: {e}")
                return False


        return True
    except Exception as e:
        print(f"剪贴板复制失败: {e}")
        return False
    
def check_clipboard_tool():
    """检查系统可用的剪贴板工具"""
    tools = ['xclip', 'xsel']
    for tool in tools:
        if subprocess.run(['which', tool], capture_output=True).returncode == 0:
            print(f"已找到可用的剪贴板工具：{tool}")
            return tool
    return None



# 示例使用
if __name__ == "__main__":

    check_clipboard_tool()

# 2025-09-23 17:52:06
    if len(sys.argv) > 1:
        input_str = sys.argv[1]
        result =  create_table(input_str, header=True,title="")
        # print(json.dumps(result))  # 使用JSON确保格式正确
# 2025-11-13 09:55:41
        # result =  create_table(input_str, header=False,title="")

        # 尝试复制到剪贴板
        if copy_to_clipboard(result):
            # 同时输出到控制台（供VSCode任务显示）
            print("✓ 结果已自动复制到剪贴板，可直接粘贴使用")
            print("\n" + "="*50)
            print(result)
            print("="*50)
        else:
            # 如果复制失败，只输出结果
            print("✗ 无法自动复制到剪贴板，请手动复制以下结果:")
            print("\n" + "="*50)
            print(result)
            print("="*50)        # print(result)  # 使用JSON确保格式正确
    else:
        print("请输入参数")

    exit()


#======================================================================================================
    # 示例数据
    rows_str = '''
取值	含义	说明
'inner'	内连接	只保留两个表中都存在的键值
'outer'	外连接	保留两个表中所有的键值，缺失值用 NaN 填充
'left'	左连接	保留左表所有键值，右表没有的用 NaN 填充
'right'	右连接	保留右表所有键值，左表没有的用 NaN 填充
'''
    # create_table(rows_str, title="人员信息表")
    # create_table(rows_str, header=False)
    # create_table(rows_str, header=True,title="人员信息表")
    create_table(rows_str, header=True,title="")
    
    exit()

    print_table(rows_str)



    # 解析字符串为列表格式
    rows = parse_table_string(rows_str)
    # 打印表格
    # for row in rows:
    #     print(row)
#======================================================================================================
    # exit()

    # rows = [
    #     ["取值", "含义", "说明"],
    #     ["'inner'", "内连接", "只保留两个表中都存在的键值"],
    #     ["'outer'", "外连接", "保留两个表中所有的键值，缺失值用 NaN 填充"],
    #     ["'left'", "左连接", "保留左表所有键值，右表没有的用 NaN 填充"],
    #     ["'right'", "右连接", "保留右表所有键值，左表没有的用 NaN 填充"]
    # ]
    print_table(rows)

    exit()

#======================================================================================================

    # 示例数据
    headers = ["参数", "类型", "说明", "默认值"]
    rows = [
        ["user_id", "int", "用户唯一标识符", "无"],
        ["username", "str", "用户名，长度3-20字符", "''"],
        ["email", "str", "用户邮箱地址，必须有效格式", "''"],
        ["is_active", "bool", "用户是否激活", "True"]
    ]
    
    # 生成表格
    table = create_markdown_table(headers, rows)
    
    # 在注释中使用
    comment = f'''
"""
数据库用户表字段说明:

{table}

注意事项:
- 所有字符串字段均使用UTF-8编码
- 整数字段使用32位有符号整数
- 布尔字段使用0/1值存储
"""
'''
    print(comment)